using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Generic;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX.Direct3D.CustomVertex;

namespace GraphicsAPIs
{
	public partial class DrawingBox : PictureBox
	{
		private Device _dev;
		public Device device
		{
			get { return _dev; }
			set { _dev = value; }
		}
		List < GraphicsBuffer<PositionColored> > Polygons;
		GraphicsBuffer<PositionColored> Lines;

		public DrawingBox()
		{
			InitializeComponent();
			InitializeDevice();
			InitializeCam();
		}
		
		public void InitializeDevice()
		{
			PresentParameters pres = new PresentParameters();
			pres.IsWindowed = true;
			pres.SwapEffect = SwapEffect.Discard;
			pres.EnableAutoDepthStencil = true;
			pres.AutoDepthStencilFormat = DepthFormat.D16;
			device = new Device(0, DeviceType.Hardware, this.Handle, CreateFlags.SoftwareVertexProcessing, pres);
			device.RenderState.CullMode = Cull.None;
			device.RenderState.Lighting = false;
			InitializeCam();
		}

		private void InitializeCam()
		{
			device.Transform.Projection = Matrix.PerspectiveFieldOfViewLeftHanded(
				(float)Math.PI / 4f, Width / Height, 1f, 100f);
			device.Transform.View = Matrix.LookAtLeftHanded(
				 new Vector3(0f, 0f, 8f), new Vector3(), new Vector3(0, 1, 0));
		}


		protected override void OnPaint(PaintEventArgs pe)
		{
			try
			{
				if (device == null) return;
				device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, System.Drawing.Color.CornflowerBlue, 1.0f, 0);
				device.BeginScene();
				device.VertexFormat = PositionColored.Format;
				if (Polygons != null && Polygons.Count > 0)
				{
					foreach (GraphicsBuffer<PositionColored> buffer in Polygons)
						device.DrawUserPrimitives(PrimitiveType.TriangleFan, buffer.ElementCount - 2, buffer);
				}
				if (Lines != null)
					device.DrawUserPrimitives(PrimitiveType.LineList, Lines.ElementCount / 2, Lines);
				device.EndScene();
				device.Present();
			}
			catch { }
		}

		public void End()
		{
			device.Dispose();
		}

		public void SetPolygons(List<VisualizationPackage.FileLoader.Polygon> pols)
		{
			Lines = null;
			Polygons = new List<GraphicsBuffer<PositionColored>>();
			foreach (VisualizationPackage.FileLoader.Polygon p in pols)
			{
				int nVerts = p.Vertics.Count;
				PositionColored[] points = new PositionColored[nVerts];
				int i = 0;
				foreach (VisualizationPackage.FileLoader.Vertex vert in p.Vertics)
					points[i++] = new PositionColored((float)vert.Values["X"], (float)vert.Values["Y"], (float)vert.Values["Z"], p.DrawingColor);
				VertexBuffer vb = new VertexBuffer(device, nVerts * PositionColored.StrideSize, Usage.None, VertexFormats.Transformed, Pool.Managed, null);
				GraphicsBuffer<PositionColored> current = vb.Lock<PositionColored>(0, nVerts, LockFlags.None);
				current.Write(points);
				Polygons.Add(current);
				vb.Unlock();
			}
		}

		public void SetLines(List<VisualizationPackage.FileLoader.Line> lines)
		{
			if(Polygons != null)
				Polygons.Clear();
			PositionColored V1, V2;
			VertexBuffer vb = new VertexBuffer(device, 2 * lines.Count * PositionColored.StrideSize, Usage.None, VertexFormats.Transformed, Pool.Managed, null);
			Lines = vb.Lock<PositionColored>(0, 2 * lines.Count, LockFlags.None) ;

			foreach (VisualizationPackage.FileLoader.Line ln in lines)
			{
				V1 = new PositionColored((float)ln.Vertext1.Values["X"], (float)ln.Vertext1.Values["Y"], (float)ln.Vertext1.Values["Z"], ln.DrawingColor);
				V2 = new PositionColored((float)ln.Vertex2.Values["X"], (float)ln.Vertex2.Values["Y"], (float)ln.Vertex2.Values["Z"], ln.DrawingColor);
				Lines.Write(new PositionColored[] { V1, V2 });
			}
			vb.Unlock();
		}
	}
}
